using System;
using System.Security.Cryptography;
using System.Text;

namespace Plugins
{
    /// <summary>Class used to generate and check hashes.</summary>
    public class Hash
    {
        /// <summary></summary>
        public Hash() { }

        #region Hash Choices
        /// <summary>The wanted hash function.</summary>
        public enum HashType : int
        {
            /// <summary>MD5 Hashing</summary>
            MD5,
            /// <summary>SHA1 Hashing</summary>
            SHA1,
            /// <summary>SHA256 Hashing</summary>
            SHA256,
            /// <summary>SHA384 Hashing</summary>
            SHA384,
            /// <summary>SHA512 Hashing</summary>
            SHA512
        } /* HashType */
        #endregion

        #region Public Methods
        /// <summary>Generates the hash of a text.</summary>
        /// <param name="strPlain">The text of which to generate a hash of.</param>
        /// <param name="hshType">The hash function to use.</param>
        /// <returns>The hash as a hexadecimal string.</returns>
        public static byte[] GetHash(byte[] Content, HashType hshType)
        {
            byte[] ret;
            switch (hshType)
            {
                case HashType.MD5: ret = GetMD5(Content); break;
                case HashType.SHA1: ret = GetSHA1(Content); break;
                case HashType.SHA256: ret = GetSHA256(Content); break;
                case HashType.SHA384: ret = GetSHA384(Content); break;
                case HashType.SHA512: ret = GetSHA512(Content); break;
                default: ret = null; break;
            }
            return ret;
        } /* GetHash */

        /// <summary>Checks a text with a hash.</summary>
        /// <param name="strOriginal">The text to compare the hash against.</param>
        /// <param name="strHash">The hash to compare against.</param>
        /// <param name="hshType">The type of hash.</param>
        /// <returns>True if the hash validates, false otherwise.</returns>
        public static bool CheckHash(byte[] ContentOriginal, byte[] ContentHash, HashType hshType)
        {
            byte[] origHash = GetHash(ContentOriginal, hshType);
            return (origHash == ContentHash);
        } /* CheckHash */
        #endregion

        #region Hashers
        public static string FileHash(string Filename, HashType hshType)
        {
            byte[] fileData = System.IO.File.ReadAllBytes(Filename);
            return HashToString(GetHash(fileData, hshType));
        }

        public static string HashToString(byte[] HashValue)
        {
            string strHex="";
            foreach (byte b in HashValue)
            {
                strHex += String.Format("{0:x2}", b);
            }
            return strHex;

        }
        private static byte[] GetMD5(byte[] Content)
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                return md5.ComputeHash(Content);
            }
        } /* GetMD5 */

        private static byte[] GetSHA1(byte[] Content)
        {
            using (SHA1Managed SHhash = new SHA1Managed())
            {
                return SHhash.ComputeHash(Content);
            }
        } /* GetSHA1 */

        private static byte[] GetSHA256(byte[] Content)
        {
            using (SHA256Managed SHhash = new SHA256Managed())
            {
                return SHhash.ComputeHash(Content);
            }
        } /* GetSHA256 */

        private static byte[] GetSHA384(byte[] Content)
        {
            using (SHA384Managed SHhash = new SHA384Managed())
            {
                return SHhash.ComputeHash(Content);
            }
        } /* GetSHA384 */

        private static byte[] GetSHA512(byte[] Content)
        {
            using (SHA512Managed SHhash = new SHA512Managed())
            {
                return SHhash.ComputeHash(Content);
            }
        } /* GetSHA512 */
        #endregion
    } /* Hash */
}